
# stage 3 작업 

----------------------------------------------------------------

  0. [Python Code]
    - stage 2 쪼개진 결과물 중 일부만 입력으로 사용
      - 입력: `C-###_claim_information.json`
      - [청구권/청구취지/청구원인]만 추출하고 조립
    - 조립 정보는 `C-###_query_info_legal_facts.json`으로 저장

[추출 정보]:
- claim_id
- case_kind
- claim_title
- plaintiffs
- defendants
- claim_statement
- relief_summary
- cause_summary

----------------------------------------------------------------

  1. [Map-Reduce]-[요건사실 쿼리 생성 + DB 검색 + 결과 조립]
  1.1 [쿼리 생성]
    - 개별 청구권에 대한 요건사실 쿼리 생성[Gemini-3.1-Flash-Lite-Preview/reasoning=high/verbosity=low]
      - 입력: `C-###_query_info_legal_facts.json` + Default_Agent/Keywords_Criteria.txt
    - 생성쿼리는 `C-###_query_for_legal_facts.json`으로 저장

[작업 과정]:
1. DB 매핑
2. 쿼리생성규칙 주입
3. JSON Schema 부여

----------------------------------------------------------------

  1.2 [DB 검색]
    - 생성 쿼리로 Weaviate DB 검색 
      - 입력: `C-###_query_for_legal_facts.json`
      - 요건사실 중요도 순으로 상위 6개만 추출 = 요건요소 6개
    - 검색결과는 `C-###_legal_elements.json`

----------------------------------------------------------------

  1.3 [검색결과 문서화]
    - 추출한 요건요소에 대한 요건사실 서술 [Gemini-3.1-Flash-Lite-Preview/reasoning=high/verbosity=high]
        - 입력: `C-###_legal_elements.json` + `C-###_input_legal_fact.json`
    - 개별청구권별 요건사실 문서(JSON)생성: `C-###_legal_facts.json`

----------------------------------------------------------------

  2. [Python Code]-[종합입력정보 생성]
    - 입력: `C-###_legal_facts.json`(개별청구권별 요건사실 정보) + 기존 `C-###_claim_information.json`
    - 정보 조립 및 문서 생성 
      - 조합정보: [청구권/청구취지/청구원인/요건요소/요건사실/F-###(fact_id)/F-###별 핵심 정보]
      - 문서: `C-###_key_info.json`
        - 문서 JSON Schema 미리 지정

----------------------------------------------------------------

  3. [Map-Reduce]-[예상항변-재반박 도출]
    - 개별 청구권별 작업[Gemini-3.1-Pro-Preview/reasoning=high/verbosity=high]
      - 입력: `C-###_key_info.json`(개별 청구권 조합 문서)
      - 청구취지에 대한 가장 가능성 높은 예상항변(요건요소별) 2개 및 그에 대한 재반박 논리 2개 생성
      - 개별 청구권 조합 문서 재조립: 청구권/청구취지/청구원인/요건요소/요건사실/예상항변/재반박
      - 재조립한 문서는 `C-###_essential_info.json`로 생성

----------------------------------------------------------------

  4. [Python Code]-[기계적으로 청구항변재반박전략서.md 생성]
    - 입력: `C-###_essential_info.json` + `client_goal.json`
    - 청구항변재반박전략서.md 조립
      - 1. 사건개요: client_goal.json 사용
      - 2. 당사자 구조
      - 3. 청구 마스터 표
        - 3.1 청구권 구조도: [청구ID/청구권/사건종류/원고/피고]
        - 3.2 청구권 상세 정보 표(청구권 갯수만큼 stack)
            - 제목: C-###: [string]
            - 항목(1열): 청구취지, 청구원인, 요건요소, 요건사실, 서증목록, 예상항변, 예상항변 요건요소, 재반박, 재반박 요건요소
            - 내용(2열): 항목별 내용 기입



-------------------------------------------------------------------
-------------------------------------------------------------------
-------------------------------------------------------------------
-------------------------------------------------------------------

# 연구용 프롬프트

-------------------------------------------------------------------

## 0. 단계 작업

개발 중인 법률 에이전트는 총 5단계(5 stages: stage 1, stage 2, stage 3, stage 4, stage 5)의 작업흐름(workflow)을 가지고 있다. `Legal_Agent_V4_v5_copy.yaml`의 stage 1을 실행하여 얻은 결과물들은 `Stage_1_Results` 폴더에 저장되어 있다. 그리고 에이전트의 stage 2 작업은 `Legal_Agent_V4_v5_copy.yaml`가 아니라, `stage_2_task_A_B_C.yml` > `stage_2_claim_description_mapreduce.yml` > `stage_2_task_D.yml`을 순서대로 실행하도록 정의되어 있다. 

`stage_2_task_A_B_C.yml` > `stage_2_claim_description_mapreduce.yml` > `stage_2_task_D.yml` 순서대로 실행하여 얻은 stage 2 결과물들은 `Stage_2_Results` 폴더에 저장되어 있다. 

`stage_2_task_A_B_C.yml`을 실행하여 얻은 결과물은 `Stage_2_Results/Task_A_B_C` 폴더에 저장되어 있다. 
`stage_2_claim_description_mapreduce.yml`을 실행하여 얻은 결과물은 `Stage_2_Results/Task_D_pre` 폴더에 저장되어 있다. 
`stage_2_task_D.yml`을 실행하여 얻은 결과물은 `Stage_2_Results/Task_D` 폴더에 저장되어 있다. 


Stage 3의 0번째 단계는 python code를 사용하여 기계적으로 정보를 추출하는 작업이다. 이 작업은 개별 청구권(claim)들의 청구취지와 청구원인에 해당하는 요건사실을 외부 Weaviate DB에서 검색하여 매칭되는 자료를 가져오기 위한 쿼리(query)를 생성하기 위해 사용할 정보를 조합하는 것이다. 즉 쿼리 생성용 정보를 생성하는 작업인 것이다. 

`Stage_2_Results/Task_D` 폴더에 저장되어 있는 개별 `C-###_claim_description.json` 문서들에서 아래 필드 정보들만 추출하여 `C-###_query_info_legal_facts.json`로 저장하는 것이 0번째 단계의 목표다. 

---
* 추출 필드 정보
- claim_id
- case_kind
- claim_title
- plaintiffs
- defendants
- claim_statement
- relief_summary
- cause_summary
---

Python Code 생성 시 format과 사용할 도구 등을 정의할 벤치마크 코드 2가지는 아래와 같다. 
- `stage_2_task_A_B_C.yml`의 **`task_name: Task_A`-`mcp: code-executor`**
- `stage_2_task_D.yml`의 **`task_name: load_claim_info`-`mcp: code-executor`**

벤치마크 코드를 참조하여 개별 `C-###_claim_description.json`들을 `C-###_query_info_legal_facts.json`로 생성하는 python code를 작성하라. 

작성한 코드는 `stage_3_task_0_code.txt`에 저장하라. 


-------------------------------------------------------------------

## 1단계 작업

  1. [Map-Reduce]-[요건사실 쿼리 생성 + DB 검색 + 결과 조립]
  1.1 [쿼리 생성]
    - 개별 청구권에 대한 요건사실 쿼리 생성[Gemini-3.1-Flash-Lite-Preview/reasoning=high/verbosity=low]
      - 입력: `C-###_query_info_legal_facts.json` + Default_Agent/Keywords_Criteria.txt
    - 생성쿼리는 `C-###_query_for_legal_facts.json`으로 저장

[작업 과정]:
1. DB 매핑
2. 쿼리생성규칙 주입
3. JSON Schema 부여

-------------------------------------------------------------------
## 1.1 단계 작업 - 프롬프트 작업 설명

이제 Stage 3의 1단계의 첫번째 작업은 0단계 작업에서 얻은 `C-###_query_info_legal_facts.json`로부터 Weaviate DB 검색을 위한 쿼리를 생성하는 것이다. 아래에 작업 지시문(<description>)을 상세하게 묘사하였다. 

<description>
1. 입출력 파일 (HARD)
- IN (필수)
* `C-###_query_for_legal_facts.json`
* `Default_Agent/DB_legally_required_facts_description.md`
- OUT:
* `C_###_query_legal_facts_search.json`

2. DB 매핑 (mapped_collection, mapped_tenant, tenant_status)
`Default_Agent/DB_legally_required_facts_description.md` 표를 기준으로 다음 절차를 **결정론적으로** 수행한다.
  1. **Exact match 1차:**
   `사건종류` == 표의 `사건 종류` 셀과 완전 일치하면 그 row를 채택한다.
  2. **유사어 기반 2차(결정론):**
   1차가 실패하면, 해당 표의 `사건 종류 유사어`(쉼표로 구분된 목록) 중 하나가 `사건종류`와 완전 일치하면 그 row를 채택한다.
  3. **부분 포함 3차(결정론):**
   1·2차가 실패하면,
     * `사건종류`가 `사건 종류` 셀 문자열에 포함되거나,
     * `사건 종류` 셀이 `사건종류` 문자열에 포함되는 경우
   가장 먼저 매칭되는 row(표의 위에서 아래 순서)를 채택한다.
  4. **매핑 성공 시:**
    * `Weaviate DB` 셀에서 `[Collection: X] - [Tenant: Y]`를 파싱하여
      * `mapped_collection = X`
      * `mapped_tenant = Y`
  5. **매핑 실패 시:**
    * `mapped_collection = "UNKNOWN"`
    * `mapped_tenant = "UNKNOWN"`
    * `validation_warnings[]`에 경고 1건을 추가한다.

3. 쿼리 생성 규칙 (semantic unit ≤ 6, HARD)
3.1 노이즈 차단(사건 고유 사실 금지, HARD)
`search_params.query`(= query_text)는 다음 정보를 포함하면 안 된다.
* 인명/법인명/기관명
* 금액/이자율/채권액 등 수치
* 일자/기간
* 주소/지번/계좌/부동산 특정표지
* 사건 고유의 개별 사실관계(예: 특정 부동산 명칭)

허용되는 것은 **법률 개념어** 및 **요건사실/항변/입증책임 구조를 지시하는 일반어**에 한정한다.

3.2 앵커 프리픽스(고정, HARD)

모든 쿼리 문자열은 반드시 다음 3개 앵커로 시작한다(고정):
* `"요건사실 항변 입증책임"`

이를 **anchor_units=3**으로 간주한다.

3.3 후보 개념어 풀 구성(최대 10개, HARD)

각 “사건종류 그룹”마다 후보 풀을 만든다(아래 6.1 그룹화 참조).
후보 풀의 입력 텍스트 원천(허용 범위):
* (A) `사건종류`(case_kind 또는 macro_category로 결정된 값)
* (B) 해당 그룹의 대표 claim(그룹 내 claim_id가 가장 작은 청구)의
  * `claim_title`, `relief_summary`, `cause_summary`
* (C) DB 매핑에 성공한 경우, 해당 사건종류 row의 `사건 종류 유사어`(법률 개념어로서만 사용)

후보 풀 생성 규칙(결정론):
1. 위 텍스트를 **좌→우(문장 순서)**로 훑으면서, “법률 개념어로 볼 수 있는 짧은 구(phrase)”를 추출한다.
2. 추출 시 **노이즈 차단 규칙(3.1)**을 위반하는 토큰은 즉시 제외한다.
3. 중복 제거는 아래 “단순 표준화”만 사용한다(추론 기반 동의어 확장 금지):
   * 공백/구두점 차이만 있는 동일 표현은 1개로 합친다.
   * (C)의 유사어 목록에 포함된 표현은 “사건종류의 표준 표현”으로 흡수한다.
4. 후보 풀은 **최대 10개**까지 유지하고, 10개를 채우면 즉시 중단한다.

3.4 case_units 선택(최대 3개, HARD)
* `case_units`는 후보 풀에서 **최대 3개**만 선택한다.
* 총 semantic unit은 `anchor(3) + case_units(k)`로 계산하며, **k ≤ 3**을 지킨다.

선택 우선순위(결정론, tie-break 포함):
1. `사건종류`(문자열)에서 직접 추출된 개념어를 우선한다.
2. 남는 슬롯은 대표 claim의 `claim_title → relief_summary → cause_summary` 순으로,
   **더 먼저 등장**한 개념어를 우선한다.
3. 여전히 동률이면 **가나다(사전순)**로 tie-break.

3.5 query_text 구성(HARD)
* `query_text = "요건사실 항변 입증책임" + " " + " ".join(case_units)`
* 단, query_text의 길이가 **100자 초과**이면:
  * `case_units`의 **마지막 항목부터** 제거하여 100자 이하로 맞춘다.
  * 이때도 `case_units`가 1개 이상 유지되어야 한다.

만약 위 규칙으로도 `case_units`를 1개 이상 유지하지 못하면:
* 해당 사건종류 그룹에 대한 **query를 생성하지 않는다.**
* `validation_warnings[]`에 경고 1건을 추가한다.

4. 쿼리 그룹화 및 query_id 부여 (운영 친화, 결정론)
4.1 그룹화 규칙
아래 키가 동일한 청구들을 하나의 그룹으로 묶어 **그룹당 1개 query**를 만든다.
* `사건종류`
* `mapped_collection`
* `mapped_tenant`

그룹의 대표 claim은 **claim_id가 가장 작은 청구**로 한다(개념어 추출 및 case_units 선택에 사용).

4.2 query_id 부여
* 그룹을 “대표 claim_id 오름차순”으로 정렬한다.
* 정렬된 순서대로 `Q-001`, `Q-002`, … 를 부여한다.

5. Hybrid Search 파라미터 (타입 강제, HARD)
각 query는 `search_params`에 아래 키를 **모두 포함**해야 하며, 타입을 강제한다.

5.1 search_params 필수 키(타입 강제)

* `collection_name`: string  (=`mapped_collection`)
* `tenant`: string           (=`mapped_tenant`)
* `query`: string            (=`query_text`)
* `alpha`: number(float)     (문자열 금지)
* `limit`: integer           (문자열 금지)
* `query_properties`: array[string] (문자열 JSON 금지)
* `fusion_type`: string      (**항상 "relativeScoreFusion" 사용**)
* `bm25_operator`: string    ("or" 또는 "and")
* `bm25_minimum_match`: integer (문자열 금지)

5.2 기본값(HARD)

* `fusion_type = "relativeScoreFusion"`  (고정)
* `limit = 8`
* `query_properties = ["content"]`
* `bm25_operator = "or"` (기본)

5.3 BM25 minimum match 강제(앵커 3단어 문제 해결, HARD)

* anchor_units = 3
* k = len(case_units) (1~3)
* `bm25_minimum_match = anchor_units + min(k, 2)`

  * k=1 → 4
  * k=2 → 5
  * k=3 → 5

5.4 alpha 결정 규칙(HARD, 결정론)
사건종류 문자열에 아래 키워드가 포함되면 해당 alpha를 사용한다.

* "사해행위취소" 포함 → `alpha = 0.45`
* "구상금" 포함 → `alpha = 0.35`
* "대여금" 또는 "보증" 포함 → `alpha = 0.25`
* 그 외 → `alpha = 0.35`

6. 출력 JSON 구성 (스키마 준수, HARD)
6.1 최상위 구조
출력은 반드시 아래 3개 최상위 키를 포함한다.

* `claims`: array
* `queries`: array
* `query_summary`: object
  (선택) `validation_warnings`: array[string]

6.2 claims 배열
반드시 다음 키를 포함한다:
* `claim_id` (string)
* `claim_title` (string)
* `case_kind` (string)
* `mapped_collection` (string; 실패 시 "UNKNOWN")
* `mapped_tenant` (string; 실패 시 "UNKNOWN")

6.3 queries 배열
각 사건종류 그룹(6.1)마다 1개 원소를 생성한다. 단, 아래 경우에는 생성하지 않는다.

* DB 매핑 실패(tenant_status="UNCONFIRMED")로 collection/tenant가 "UNKNOWN"인 경우
* case_units를 1개 이상 확보하지 못해 query_text를 만들 수 없는 경우

각 queries 원소는 반드시 다음 키를 포함한다.

* `query_id` ("C-###-Q-001"…)
* `applicable_claim_ids` (array[string])  ← claim_id (C-###)
* `case_kind` (string)
* `purpose` = "요건사실 검색" (고정)
* `search_params` (5.1의 타입 강제 준수)
* `fusion_type` (RELATIVE_SCORE 강제)
</description>

작업지시문(<description>)에 추가적으로 아래의 정보(<추가정보>)를 참고하여 LLM이 1단계의 첫번째 작업을 가장 효율적으로 수행할 수 있도록 프롬프트를 작성하여라. 프롬프트 작성의 기준은 
1. 목적 달성 정도
2. 토큰 경제성
3. LLM 작업 속도
의 세가지다. 그리고 이 단계에서 LLM은 오로지 추론(inference)을 통해서만 작업을 수행해야 한다. 

또한, 이 프롬프트에는 JSON Schema도 포함되어야 한다. 

작성한 프롬프트는 `stage_3_task_1_1.txt`로 생성하라. 

<추가정보>
## Weaviate DB의 hybrid search에 대한 정보 문서: https://docs.weaviate.io/weaviate/search/hybrid

## 출력 JSON Schema에 반드시 포함되어야 할 필드:
    "SearchParams": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "collection_name",
        "tenant",
        "query",
        "alpha",
        "limit",
        "query_properties",
        "fusion_type",
        "bm25_operator",
        "bm25_minimum_match"
      ],
      "properties": {
        "collection_name": { "type": "string" },
        "tenant": { "type": "string" },
        "query": { "type": "string" },
        "alpha": { "type": "number", "minimum": 0, "maximum": 1 },
        "limit": { "type": "integer", "minimum": 1 },
        "query_properties": {
          "type": "array",
          "minItems": 1,
          "items": { "type": "string" }
        },
        "fusion_type": { "type": "string" },
        "bm25_operator": { "type": "string", "enum": ["or", "and"] },
        "bm25_minimum_match": { "type": "integer", "minimum": 1 }
      }
</추가정보>

-------------------------------------------------------------------


# 1.2 단계 작업

  1.2 [DB 검색]
    - 생성 쿼리로 Weaviate DB 검색 
      - 입력: `C-###_query_for_legal_facts.json`
      - 요건사실 중요도 순으로 상위 6개만 추출 = 요건요소 6개
    - 검색결과는 `C-###_legal_elements.json`



























































